﻿using System;
using System.Custom.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Reflection;
using Gizmox.WebGUI.Common.Resources;
using Gizmox.WebGUI.Forms;
using Gizmox.WebGUI.Forms.Layout;
using Gizmox.WebGUI.Forms.Skins;

namespace CoCoon.Forms.Ribbon
{
    public static partial class RibbonBarExtension
    {
        #region tools

        public static TabControl GetTabControl(this RibbonBar bar)
        {
            PropertyInfo pi = typeof(RibbonBar).GetProperty("TabControl",
                                                  BindingFlags.Instance | BindingFlags.Static |
                                                  BindingFlags.NonPublic);
            var tc = (TabControl)pi.GetValue(bar, null);
            return tc;
        }

        public static RibbonBar ShowRibbonTabs(this RibbonBar bar, bool visible)
        {
            PropertyInfo pi = typeof(RibbonBar).GetProperty("TabControl",
                                                             BindingFlags.Instance | BindingFlags.Static |
                                                             BindingFlags.NonPublic);
            var tc = (TabControl)pi.GetValue(bar, null);
            tc.Appearance = visible ? TabAppearance.Normal : TabAppearance.Logical;
            return bar;
        }
        #endregion tools


        #region StartMenu
        #endregion

        #region Pages

        public static RibbonBarItemContainer Container(this RibbonBarItem item)
        {
            if (item is RibbonBarItemContainer)
                return item as RibbonBarItemContainer;
            return Container(Owner(item));
        }

        public static RibbonBarGroup Group(this RibbonBarItem item)
        {
            if (item is RibbonBarGroup)
                return item as RibbonBarGroup;
            return Group(Owner(item));
        }
        public static RibbonBarItem Owner(this RibbonBarItem item)
        {
            PropertyInfo pi = typeof(RibbonBarItem).GetProperty("Owner",
                                                                 BindingFlags.Instance | BindingFlags.Static |
                                                                 BindingFlags.NonPublic);
            var bar = (RibbonBarItem)pi.GetValue(item, null);
            return bar;
        }

        public static RibbonBarPage Page(this RibbonBarItem item)
        {
            var group = Group(item);
            return Page(@group);
        }

        public static RibbonBarPage Page(this RibbonBarGroup item)
        {
            var ribbon = Ribbon(item);
            return ribbon.Pages.FirstOrDefault(page => Enumerable.Contains(page.Groups, item));
        }
        public static RibbonBar Ribbon(this RibbonBarPage page)
        {
            PropertyInfo pi = typeof(RibbonBarPage).GetProperty("RibbonBar",
                                                                 BindingFlags.Instance | BindingFlags.Static |
                                                                 BindingFlags.NonPublic);
            var bar = (RibbonBar)pi.GetValue(page, null);
            return bar;
        }

        public static RibbonBar Ribbon(this RibbonBarGroup group)
        {
            PropertyInfo pi = typeof(RibbonBarGroup).GetProperty("RibbonBar",
                                                                  BindingFlags.Instance | BindingFlags.Static |
                                                                  BindingFlags.NonPublic);
            var bar = (RibbonBar)pi.GetValue(group, null);
            return bar;
        }

        #endregion Navigation

        #region AddItems

        public static RibbonBarButtonItem AddButton(this RibbonBarItem item,
                                                       string text,
                                                       string toolTip,
                                                       string icon,
                                                       EventHandler clickHandler = null,
                                                       MenuEventHandler menuHandler = null,
                                                       object tag = null)
        {
            var container = Container(item);
            var iconSize = container is RibbonBarGroup ? 32 : 16;
            var b = new RibbonBarButtonItem
            {
                Text = text,
                ToolTip = toolTip,
                Image = CreateIconHandle(icon, iconSize),
                Tag = tag
            };
            if (clickHandler != null) b.Click += clickHandler;
            if (menuHandler != null) b.MenuClick += menuHandler;
            container.Items.Add(b);
            return b;
        }

        public static RibbonBarColorComboBoxItem AddColorComboBox(this RibbonBarItem item)
        {
            var container = Container(item);
            var i = new RibbonBarColorComboBoxItem();
            container.Items.Add(i);
            return i;
        }

        public static RibbonBarComboBoxItem AddComboBox(this RibbonBarItem item,
                                                         object dataSource,
                                                         string displayMember,
                                                         string valueMember,
                                                         string command,
                                                         EventHandler handler)
        {
            var container = Container(item);
            var i = new RibbonBarComboBoxItem
            {
                DataSource = dataSource,
                DisplayMember = displayMember,
                ValueMember = valueMember,
                Tag = command
            };
            var c = i.Control as ComboBox;
            Debug.Assert(c != null, "c != null");
            c.SelectedValueChanged += handler;
            container.Items.Add(i);
            return i;
        }

        public static RibbonBarDateTimePickerItem AddDateTimePicker(this RibbonBarItem item, EventHandler valueChanged = null)
        {
            var container = Container(item);
            var i = new RibbonBarDateTimePickerItem { };
            if (valueChanged != null) i.ValueChanged += valueChanged;
            container.Items.Add(i);
            return i;
        }

        public static RibbonBarFlowItem AddFlowItem(this RibbonBarItem item, int width = 100)
        {
            var group = Group(item);
            var i = new RibbonBarFlowItem();
            i.Width = width;
            group.Items.Add(i);
            return i;
        }

        public static RibbonBarComboBoxItem AddFontComboBox(this RibbonBarItem item)
        {
            var container = Container(item);
            var i = new RibbonBarComboBoxItem
            {
                DataSource = FontFamily.Families,
                DisplayMember = "Name",
                ValueMember = "Name",
                Tag = "FontSelect"
            };
            container.Items.Add(i);
            return i;
        }

        public static RibbonBarGroup AddGroup(this RibbonBarPage page, RibbonBarGroup group)
        {
            page.Groups.Add(group);
            return group;
        }

        public static RibbonBarGroup AddGroup(this RibbonBarItem item, RibbonBarGroup group)
        {
            AddGroup(Page(item), group);
            return group;
        }

        public static RibbonBarGroup AddGroup(this RibbonBarPage page, string text)
        {
            var group = new RibbonBarGroup();
            group.Text = text;
            FixPadding(@group);
            return AddGroup(page, group);
        }

        public static RibbonBarGroup AddGroup(this RibbonBarItem item, string text)
        {
            var group = new RibbonBarGroup();
            group.Text = text;
            FixPadding(@group);
            AddGroup(item, group);
            return group;
        }

        public static RibbonBarItem AddItem(this RibbonBarGroup group, RibbonBarItem item)
        {
            group.Items.Add(item);
            return item;
        }

        public static RibbonBarItem AddItem(this RibbonBarItem src, RibbonBarItem item)
        {
            var container = Container(src);
            container.Items.Add(item);
            return container;
        }

        public static RibbonBarLabelItem AddLabel(this RibbonBarItem item, string text)
        {
            var container = Container(item);
            var i = new RibbonBarLabelItem
            {
                Text = text
            };
            container.Items.Add(i);
            return i;
        }

        public static RibbonBarPage AddPage(this RibbonBarItem item, string text)
        {
            var page = new RibbonBarPage(text);
            return AddPage(Ribbon(Group(item)), page);
        }

        public static RibbonBarPage AddPage(this RibbonBar bar, string text)
        {
            var page = new RibbonBarPage(text);
            return AddPage(bar, page);
        }

        public static RibbonBarPage AddPage(this RibbonBar bar, RibbonBarPage page)
        {
            bar.Pages.Add(page);
            return page;
        }

        public static RibbonBarPushButtonItem AddPushButton(this RibbonBarItem item,
                                                           string text,
                                                           string toolTip,
                                                           string icon,
                                                           EventHandler clickHandler = null,
                                                           EventHandler<EventArgs<bool>> pushHandler = null,
                                                           string pushGroup = null,
                                                           object tag = null,
                                                           bool pushed = false)
        {
            var container = Container(item);

            var iconSize = container is RibbonBarGroup ? 32 : 16;
            var b = new RibbonBarPushButtonItem
            {
                Text = text,
                ToolTip = toolTip,
                Image = CreateIconHandle(icon, iconSize),
                PushGroup = pushGroup,
                Pushed = pushed
            };

            b.Button.Tag = tag;
            if (clickHandler != null) b.Click += clickHandler;
            if (pushHandler != null) b.PushChanged += pushHandler;
            container.Items.Add(b);

            if (container is RibbonBarStackItem)
                b.Control.CustomStyle = "RibbonBarPushMedium";
            if (container is RibbonBarToolBarItem)
                b.Control.CustomStyle = "RibbonBarPushSmall";
            return b;
        }

        public static RibbonBarSearchItem AddSearch(this RibbonBarItem item,
            string watterMarkText,
            EventHandler<EventArgs<string>> search,
            EventHandler clear)
        {
            var container = Container(item);

            var i = new RibbonBarSearchItem { WatermarkText = watterMarkText };
            if (search != null) i.Search += search;
            i.Clear += clear;
            container.Items.Add(i);
            return i;
        }

        public static RibbonBarItemContainer AddStackItem(this RibbonBarItem item)
        {
            var group = Group(item);
            var stack = new RibbonBarStackItem();
            group.Items.Add(stack);
            return stack;
        }

        public static RibbonBarGroup Advanced(this RibbonBarGroup group)
        {
            group.HasAdvanced = true;
            return group;
        }

        public static T Assign<T>(this T item, out T to) where T : RibbonBarItem
        {
            to = item;
            return item;
        }

        public static RibbonBarItem Disable(this RibbonBarItem item)
        {
            item.Enabled = false;
            return item;
        }

        public static RibbonBarItem Enable(this RibbonBarItem item, bool enabled = true)
        {
            item.Enabled = enabled;
            return item;
        }

        public static T OnClick<T>(this T item, EventHandler handler) where T : RibbonBarButtonItem
        {
            if (handler != null) item.Click += handler;
            return item;
        }

        public static T OnMenuClick<T>(this T item, MenuEventHandler handler) where T : RibbonBarButtonItem
        {
            if (handler != null) item.MenuClick += handler;
            return item;
        }

        public static RibbonBarPushButtonItem Push(this RibbonBarPushButtonItem item, bool isPushed = true)
        {
            item.Pushed = isPushed;
            return item;
        }

        public static T Tag<T>(this T item, object tag) where T : RibbonBarItem
        {
            item.Tag = tag;
            return item;
        }
         public static RibbonBarCheckButtonItem AddCheckButton(this RibbonBarItem item,
                                                              string text,
                                                              string toolTip,
                                                              string icon,
                                                              object tag = null
            )
        {
            var container = item.Container();
            var b = new RibbonBarCheckButtonItem
                {
                    Text = text,
                    ToolTip = toolTip,
                    Image = CreateIconHandle(icon, 16),
                    Tag = tag,
                };
            container.Items.Add(b);
            return b;
        }       
        
        public static RibbonBarTextBoxItem AddTextBox(this RibbonBarItem item,
                                                              string text = null,
                                                              string toolTip = null,
                                                              object tag = null)
        {
            var container = item.Container();
            var b = new RibbonBarTextBoxItem
                {
                    Text = text,
                    ToolTip = toolTip,
                    Tag = tag
                };
            container.Items.Add(b);
            return b;    
        }
        
        #endregion AddItems

        public static RibbonBarGroup CopyTo(this RibbonBarGroup source, RibbonBarGroup destination, bool append = false)
        {
            if (!append) destination.Items.Clear();
            foreach (RibbonBarItem item in source.Items)
            {
                destination.Items.Add(item);
            }
            return destination;
        }

        public static RibbonBarGroup CreateEmptyGroup(string strGroupName)
        {
            var objGroup = new RibbonBarGroup();
            objGroup.Text = strGroupName;
            return objGroup;
        }

        public static RibbonBarItem FixGroupWidth(this RibbonBarItem item)
        {
            var group = item.Group();
            if (@group == null) return item;
            int width = @group.Control.Controls.Cast<Control>().Sum(control => control.Width);
            var num = Math.Max(20, width);
            var ribbonBarGroupBoxSkin = new RibbonBarGroupBoxSkin();
            group.Control.Width = num + (group.Control.Padding.Horizontal + ribbonBarGroupBoxSkin.LeftFrameWidth + ribbonBarGroupBoxSkin.RightFrameWidth);
            return item;
        }

        public static RibbonBarGroup FixPadding(this RibbonBarGroup group)
        {
            group.Control.Padding = new Padding(2, 0, 0, 14);
            return group;
        }
        public static RibbonBarItem Width(this RibbonBarItem item, int width)
        {
            item.Control.Width = width;
            item.FixGroupWidth();
            return item;
        }

        #region Bindings
        public static RibbonBarItem Bind(this RibbonBarItem item, string controlProperty, object o, string objectProperty)
        {
            item.Control.DataBindings.Add(controlProperty, o, objectProperty);
            return item;
        }
        #endregion

#if BARAB
        private static ResourceHandle CreateIconHandle(string strIcon, int size = 32)
        {
            ResourceHandle handle = CoCoon.Extensions.ResMan.LoadIcon(strIcon, size);
            return handle;
        }
#else
        private static ResourceHandle CreateIconHandle(string strIcon, int size = 32)
        {
            ResourceHandle handle = new IconResourceHandle(strIcon + "." + size + ".png");
            return handle;
        }
#endif
    }
}